#ifndef SCRIPT_API_H
#define SCRIPT_API_H

#include "config.h"

#include <string>
#include <type_traits>

struct ScriptModuleInfo;

enum class ScriptUsage {
    eFunction, // 功能扩展，对应 IFunctionalScript
    eEditor,   // 编辑器扩展，对应 IEditorScript

    eCount,
};

class DIARY_APP_SDK_API IScript {
public:
    IScript(ScriptUsage usage, std::string title, std::string file, const ScriptModuleInfo *smi);
    virtual ~IScript();
    [[nodiscard]] const char* title() const;
    [[nodiscard]] ScriptUsage usage() const;
    [[nodiscard]] const char* lang() const;
    [[nodiscard]] const char* file() const;
    [[nodiscard]] bool reload();
    [[nodiscard]] bool reloadable() const;
    [[nodiscard]] virtual bool call(const void *arg) = 0;

    template <typename T> requires requires(T) { std::is_base_of_v<IScript, T>; }
    [[nodiscard]] inline T* as();
protected:
    virtual bool real_reload();

    ScriptUsage const usage_;
    std::string const title_;
    std::string const file_;
    const ScriptModuleInfo* const smi_;
};

class DIARY_APP_SDK_API IFunctionalScript: public IScript {
public:
    IFunctionalScript(std::string title, std::string file, const ScriptModuleInfo *smi);

    bool call (const void *) final;

    virtual void execute() = 0;
};

class DIARY_APP_SDK_API IEditorScript: public IScript {
public:
    enum EditorTarget {
        eItem,
        eDay,
        eMonth,
        eYear,

        eCount,
    };

    IEditorScript(EditorTarget target, std::string title, std::string file, const ScriptModuleInfo *smi);

    [[nodiscard]] EditorTarget target() const;

    bool call (const void *arg) final;

    virtual void execute(const void *data) = 0;
protected:
    EditorTarget const apply_target_;
};

DIARY_APP_SDK_API
IEditorScript::EditorTarget EditorTargetFromString(const char *target);

DIARY_APP_SDK_API
const char* EditorTargetToString(IEditorScript::EditorTarget target);

template<typename T> requires requires(T) { std::is_base_of_v<IScript, T>; }
inline T* IScript::as() {
    return dynamic_cast<T*>(this);
}

#endif /* SCRIPT_API_H */
